import { ts,  NodePredicate, rule } from 'qvog-dsl';

const SEVERITY = 2;
const DOC_PATH = 'docs/consistent-indexed-object-style.md';
const DESCRIPTION = 'Require or disallow the Record type.';

const IndexableNode: NodePredicate<ts.Node> = {
  is(node: ts.Node): node is ts.Node {
    return ts.isTypeAliasDeclaration(node) ||
      ts.isInterfaceDeclaration(node) ||
      ts.isTypeLiteralNode(node);
  }
};

const DEFAULT_STYLE = 'record';

export default rule<{ context: Object[] }>()
  .match(IndexableNode)
  .when((node: ts.Node, { props }): boolean => {
    const options = props.context || [DEFAULT_STYLE];
    const useRecordStyle = options.includes('record');

    if (ts.isTypeLiteralNode(node)) {
      const hasIndexSignature = node.members.some(m => ts.isIndexSignatureDeclaration(m));
      return useRecordStyle && hasIndexSignature;
    }

    if (ts.isTypeReferenceNode(node) &&
      ts.isIdentifier(node.typeName) &&
      node.typeName.text === 'Record') {
      return !useRecordStyle;
    }

    return false;
  })
  .report({
    severity: SEVERITY,
    description: DESCRIPTION,
    docPath: DOC_PATH
  });